/************************************************************************/
/* Game                                                                 */
/************************************************************************/
#include "Game/Managers/TowerManager.h"

namespace TD_Game {

	TowerManager * TowerManager::m_pTowerManager = NULL;

	/************************************************************************/
	/* Singleton                                                            */
	/************************************************************************/
	TowerManager * TowerManager::getInstance() {
		if(m_pTowerManager == NULL) {
			m_pTowerManager = new TowerManager();
		}
		return(m_pTowerManager);
	}

	/************************************************************************/
	/* ctors an dtors                                                       */
	/************************************************************************/
	TowerManager::TowerManager() : Manager<BaseTower>() {
		m_pTileset = NULL;
		m_pTurretTilemap = NULL;
		m_updateTowers = true;
	}

	TowerManager::TowerManager(const TowerManager &rhs) : Manager<BaseTower>(rhs) {
		m_pTileset = rhs.getTileset();
		m_pTurretTilemap = rhs.getTilemap();
	}

	TowerManager & TowerManager::operator = (const TowerManager &rhs) {
		Manager<BaseTower>::operator=(rhs);
		m_pTileset = rhs.getTileset();
		m_pTurretTilemap = rhs.getTilemap();
		return(*this);
	}


	/************************************************************************/
	/* Functionalities                                                      */
	/************************************************************************/
	bool TowerManager::loadTilemap(const Tileset *g_pTileset, const string &tileMapStr, const Coord2D & mapPosition, const Coord2D &numTiles) {
		m_pTileset = g_pTileset;

		//Delete previous instantiated object.
		if(m_pTurretTilemap != NULL) {
			delete m_pTurretTilemap;
		} 

		/** Turret map is responsible for raw rendering of the towers. */
		m_pTurretTilemap = new TurretTilemap(m_pTileset);
		if(!m_pTurretTilemap->loadTilemap(tileMapStr, mapPosition, numTiles)) {
			return false;
		}

		
		for(int i = 0; i < numTiles.y; i++) {
			for(int j = 0; j < numTiles.x; j++) {
				if(m_pTurretTilemap->getTileMatrix()(i, j) == 1) {
					BaseTower *pTurret = TowerFactory::createBaseTower(ancientTower, m_currObjId, m_pTurretTilemap->getTileposition(i, j) + Coord2D(24, 0));
					createObject(pTurret);
				}
			}
		}

		return true;
	}

	void TowerManager::createTower(const Coord2D &towerPos, towerTypes towerType) {
		unsigned int objID = towerPos.x + (towerPos.y * 1000);
		BaseTower *pTurret = TowerFactory::createBaseTower(towerType, objID, towerPos);
		createObject(objID, pTurret);
		m_renderQueue.insert(objID);
	}

	void TowerManager::update(int deltaTime) {
		map<unsigned int, BaseTower *>::iterator it;
		for(it = m_sellMap.begin() ; it != m_sellMap.end();) {
			if(it->second->wasSold()) {
				deleteObject(it->first);
				m_sellMap.erase(it++);
			} else {
				it++;
			}
		}
	}

	void TowerManager::sellTower(unsigned int towerID) {
		BaseTower *pTower = static_cast<BaseTower *>(getObject(towerID));
		if(pTower) {
			m_sellMap[towerID] = pTower;
			pTower->sell();
		}
	}

	void TowerManager::render(SDL_Surface *const g_destSurface, unsigned int deltaTime) {
		update(deltaTime);
		
		set<unsigned int>::iterator it;
		for(it = m_renderQueue.begin(); it != m_renderQueue.end(); it++) {
			map<unsigned int, BaseTower *>::const_iterator iter = getObjectMap().find(*it);
			if(iter != getObjectMap().end()) {
				if(m_updateTowers) {
					iter->second->update(deltaTime);
					iter->second->render(g_destSurface, deltaTime);
				} else {
					iter->second->render(g_destSurface, 0);
				} 

			}
		}
	}

	void TowerManager::clear() {
		map<unsigned int, BaseTower *>::iterator iter;
		for(iter = m_objMap.begin(); iter != m_objMap.end(); ) {
			if(iter->second != NULL) {
				delete iter->second;
			}
			m_objMap.erase(iter++);
		}
		m_updateTowers = true;
	}
}